package main

import (
	"net"
	"os"
	"fmt"
	"bufio"
	"encoding/json"
	"strings"
)

func debug(msg string) {
	fmt.Fprintf(os.Stdout, msg+"\n")
}

// Message definition for JSON
type Message struct {
	Version int		`json:"version"`
	From	string	`json:"from"`
	To		string	`json:"to"`
	Message string	`json:"message"`
}

func listenServer(ch chan string) {
	udpAddr, e := net.ResolveUDPAddr("", ":1979")
	if e != nil {
		fmt.Fprintf(os.Stderr, "an error occured(%s)", e)
		return
	}
	udpConn, e := net.ListenUDP("udp", udpAddr)
	if e != nil {
		fmt.Fprintf(os.Stderr, "an error occured(%s)", e)
		return
	}

	buffer := make([]byte, 1024)

	debug("Waiting for a reply from a chat server ")

	for {
		l, remoteUDPAddr, _ := udpConn.ReadFromUDP(buffer)
		if e != nil {
			fmt.Println(e)
		}

		fmt.Printf("From server(%s): %s\n", remoteUDPAddr.String(), string(buffer[0:l]))

		//いっぱい帰ってくるから一番最初にうけとったやつをつかおう。。
		ch <- remoteUDPAddr.IP.String()
	}
}

func searchServer(serverIP string) {

}
func getUserName()string{
	var name string

	fmt.Printf("Please type in your name: ")
	fmt.Scanf("%s", &name)
	return name
}

func main() {
	udpAddrString := "255.255.255.255:1978"
	name := getUserName();
	listenServerCh := make(chan string)
	go listenServer(listenServerCh)

	udpAddr, _ := net.ResolveUDPAddr("", udpAddrString)
	udpConn, e := net.DialUDP("udp", nil, udpAddr)
	if e != nil {
		fmt.Println(e)
	}
	// write
	udpConn.Write([]byte("Server Query Message"))

	udpConn.Close()

	serverIPAddr := <-listenServerCh

	chat(serverIPAddr + ":1978",name)
}

func readString(reader *bufio.Reader) string {
	// Following reader.ReadString reads input until '\n' is found.
	// But note that returned string contains '\n'
	// So get rid of '\n' as well as '\r'(for Windows)
	input, _ := reader.ReadString('\n')
	trimedInput := strings.Trim(input, "\n\r")	
	return trimedInput
}

func chat(connAddr string,name string) {
	fmt.Printf("Connecting to the chat server : %s ... ", connAddr)
	sendcon, e := net.Dial("tcp", connAddr)
	if e != nil {
		fmt.Fprintf(os.Stderr, "an error occured(%s)", e)
		return
	}
	fmt.Printf("connected\n\n")

	// goroutine to receive messages from the server.
	go func() {
		buffer := make([]byte, 1024)
		for {
			var msg Message

			l, _ := sendcon.Read(buffer)

			json.Unmarshal(buffer[0:l], &msg)
			fmt.Printf("[Version = %d, From: %s, To: %s]\n", 
						msg.Version, msg.From, msg.To)
			fmt.Printf("%s\n\n", msg.Message)
		}
	}()

	reader := bufio.NewReader(os.Stdin)
	for {
		input := readString(reader)

		if input == "exit" || 
		   input == "quit" {
			sendcon.Close()
			debug("bye")
			return
		}

		if len(input) == 0 {
			continue
		}

		msg := Message{1, name, "everyone", input}
		b, _ := json.Marshal(msg)
		sendcon.Write(b)
	}
}
